macvlan 簡介
macvlan 是 linux kernel 比較新的特性,可以通過以下方法判斷當前系統是否支持:
$ modprobe macvlan
$ lsmod | grep macvlan
macvlan 19046 0
如果第一個命令報錯,或者第二個命令沒有返回,則說明當前系統不支持 macvlan,需要升級系統或者升級內核。
macvlan 允許你在主機的一個網絡接口上配置多個虛擬的網絡接口,這些網絡 interface 有自己獨立的 mac 地址,也可以配置上 ip 地址進行通信。macvlan 下的虛擬機或者容器網絡和主機在同一個網段中,共享同一個廣播域。macvlan 和 bridge 比較相似,但因為它省去了 bridge 的存在,所以配置和調試起來比較簡單,而且效率也相對高。除此之外,macvlan 自身也完美支持 VLAN。
如果希望容器或者虛擬機放在主機相同的網絡中,享受已經存在網絡棧的各種優勢,可以考慮 macvlan。
各個 linux 發行版對 macvlan 的支持
macvlan 對kernel 版本依賴:Linux kernel v3.9–3.19 and 4.0+。幾個重要發行版支持情況:
- ubuntu:>= saucy(13.10)
- RHEL(Red Hat Enterprise Linux): >= 7.0(3.10.0)
- Fedora: >=19(3.9)
- Debian: >=8(3.16)
各個發行版的 kernel 都可以自行手動升級,具體操作可以參考官方提供的文檔。
以上版本信息參考了這些資料:
- List of ubuntu versions with corresponding linux kernel version
- Red Hat Enterprise Linux Release Dates
四種模式
- private mode:過濾掉所有來自其他 macvlan 接口的報文,因此不同 macvlan 接口之間無法互相通信
- vepa(Virtual Ethernet Port Aggregator) mode: 需要主接口連接的交換機支持 VEPA/802.1Qbg 特性。所有發送出去的報文都會經過交換機,交換機作為再發送到對應的目標地址(即使目標地址就是主機上的其他 macvlan 接口),也就是 hairpin mode 模式,這個模式用在交互機上需要做過濾、統計等功能的場景。
- bridge mode:通過虛擬的交換機講主接口的所有 macvlan 接口連接在一起,這樣的話,不同 macvlan 接口之間能夠直接通信,不需要將報文發送到主機之外。這個模式下,主機外是看不到主機上 macvlan interface 之間通信的報文的。
- passthru mode:暫時沒有搞清楚這個模式要解決的問題
VEPA 和 passthru 模式下,兩個 macvlan 接口之間的通信會經過主接口兩次:第一次是發出的時候,第二次是返回的時候。這樣會影響物理接口的寬帶,也限制了不同 macvlan 接口之間通信的速度。如果多個 macvlan 接口之間通信比較頻繁,對於性能的影響會比較明顯。
private 模式下,所有的 macvlan 接口都不能互相通信,對性能影響最小。
bridge 模式下,數據報文是通過內存直接轉發的,因此效率會高一些,但是會造成 CPU 額外的計算量。
NOTE:如果要手動分配 mac 地址,請注意本地的 mac 地址最高位字節的低位第二個 bit 必須是 1。比如 02:xx:xx:xx:xx:xx
。
實驗
為了方便演示,我們會創建出來兩個 macvlan 接口,分別放到不同的 network namespace 裡。整個實驗的網絡拓撲結構如下:
首先還是創建兩個 network namespace:
[root@localhost ~]# ip netns add net1
[root@localhost ~]# ip netns add net2
然後創建 macvlan 接口:
[root@localhost ~]# ip link add link enp0s8 mac1 type macvlan
[root@localhost ~]# ip link
23: mac1@enp0s8: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT
link/ether e2:80:1c:ba:59:9c brd ff:ff:ff:ff:ff:ff
創建的格式為 ip link add link <PARENT> <NAME> type macvlan
,其中 <PARENT>
是 macvlan 接口的父 interface 名稱,<NAME>
是新建的 macvlan 接口的名稱,這個名字可以任意取。使用 ip link
可以看到我們剛創建的 macvlan 接口,除了它自己的名字之外,後面還跟著父接口的名字。
下面就是把創建的 macvlan 放到 network namespace 中,配置好 ip 地址,然後啟用它:
[root@localhost ~]# ip link set mac1@enp0s8 netns net1
Cannot find device "mac1@enp0s8"
[root@localhost ~]# ip link set mac1 netns net1
[root@localhost ~]# ip netns exec net1 ip link
23: mac1@if3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT
link/ether e2:80:1c:ba:59:9c brd ff:ff:ff:ff:ff:ff
[root@localhost ~]# ip netns exec net1 ip link set mac1 name eth0
[root@localhost ~]# ip netns exec net1 ip link
23: eth0@if3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT
link/ether e2:80:1c:ba:59:9c brd ff:ff:ff:ff:ff:ff
[root@localhost ~]# ip netns exec net1 ip addr add 192.168.8.120/24 dev eth0
[root@localhost ~]# ip netns exec net1 ip link set eth0 up
同理可以配置另外一個 macvlan 接口,可以測試兩個 ip 的連通性:
[root@localhost ~]# docker exec 1444 ping -c 3 192.168.8.120
PING 192.168.8.120 (192.168.8.120): 56 data bytes
64 bytes from 192.168.8.120: seq=0 ttl=64 time=0.130 ms
64 bytes from 192.168.8.120: seq=1 ttl=64 time=0.099 ms
64 bytes from 192.168.8.120: seq=2 ttl=64 time=0.083 ms
--- 192.168.8.120 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.083/0.104/0.130 ms
在 docker 中的使用
docker1.12 版本也正式支持了 macvlan 和 ipvlan 網絡模式。
創建 macvlan 網絡
管理 macvlan 和其他類型的網絡類似,通過 docker network
子命令就能實現。創建 macvlan 網絡的時候,需要知道主機的網段和網關地址,虛擬網絡要依附的物理網卡。
[root@localhost ~]# docker network create -d macvlan --subnet=192.168.8.0/24 --gateway=192.168.8.1 -o parent=enp0s8 mcv
9fad35e54a2f53c9314626f89cf8a705799ed382ddac01c865be1f4d04fdcb8f
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
e06b6e00dd3b bridge bridge local
823b7bb07c41 host host local
9fad35e54a2f mcv macvlan local
dc7c667aca19 none null local
選項說明:
- subnet:網絡 CIDR 地址
- gateway:網關地址
- aux-address:不要分配給容器的 ip 地址。字典,以 key=value 對出現
- ip-range:指定具體的 ip 分配區間,也是 CIDR 格式,必須是 subnet 指定範圍的子集
- opt(o):和 macvlan driver 相關的選項,以 key=value 的格式出現
- parent=eth0: 指定 parent interface
- macvlan_mode:macvlan 模式,默認是 bridge
運行容器
創建好網絡之後,我們就可以使用剛創建的網絡運行兩個容器,測試網絡的連通性。
[root@localhost ~]# docker run --net=mac192 -d --rm alpine top
5e950cf86cda7b4e6fc4bd869834943edacaaf969051293021c75330bbc18b53
[root@localhost ~]# docker run --net=mac192 -d --rm alpine top
9067c54aac79e65b3193a137e95a180a7e5cc4a2845cc664f53c17a244be3853
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9067c54aac79 alpine "top" 7 seconds ago Up 6 seconds sharp_hodgkin
5e950cf86cda alpine "top" 8 seconds ago Up 7 seconds peaceful_chandrasekhar
[root@localhost ~]# docker exec 906 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
16: eth0@if3: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UNKNOWN
link/ether 02:42:c0:a8:08:03 brd ff:ff:ff:ff:ff:ff
inet 192.168.8.3/24 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:c0ff:fea8:803/64 scope link
valid_lft forever preferred_lft forever
[root@localhost ~]# docker exec 5e9 ping -c 3 192.168.8.3
PING 192.168.8.3 (192.168.8.3): 56 data bytes
64 bytes from 192.168.8.3: seq=0 ttl=64 time=0.226 ms
64 bytes from 192.168.8.3: seq=1 ttl=64 time=0.076 ms
64 bytes from 192.168.8.3: seq=2 ttl=64 time=0.095 ms
--- 192.168.8.3 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.076/0.132/0.226 ms
需要注意的是,從容器中是無法訪問所在主機地址的:
[root@localhost ~]# docker exec 5e9 ping -c 3 192.168.8.110
PING 192.168.8.110 (192.168.8.110): 56 data bytes
--- 192.168.8.110 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss
這是 macvlan 的特性,目的是為了更好地實現網絡的隔離,和 docker 無關。
參考資料
- Macvlan and IPvlan basics
- docker docs: Getting started with macvlan network driver
- bridge vs macvlan
轉載自: http://cizixs.com/2017/02/14/network-virtualization-macvlan
留言列表